import utils from "@/libs/utils"
import MusicUtils from './utils';

class Music {
    constructor(options) {
        if (!options || !MusicUtils.isObject(options)) return;

        let settings = {
            playMode: options.PlayMode || 0, // 播放模式
            defaultVolume: options.DefaultVolume || 0.3, //播放器声音
            playMusicUrl: options.playMusicUrl || [], // 播放链接
        }

        Object.assign(this, settings, {
            playCurIdx: 0, // 当前播放索引
            modeArr: ['icon-weimingmingwenjianjia_xunhuan', 'icon-xunhuan', 'icon-suijixunhuan'],// 0:循环、1:单曲循环、2:随机循环
            playButtonArr: ['icon-bofang', 'icon-lib-play-o'], // 0:播放、1:暂停
            lyric: []
        });

        let con = options.containerSelector;
        this.dom = {
            con: con,
            lyricContainer: con.querySelector('.lyric-container'), //歌词列表框
            lyricInnerf: con.querySelector('.song-info-lyric'), //歌词列表父级框
            lyricInner: con.querySelector('.lyric-inner'), //歌词列表总长度框
            lyricP: con.querySelector('.lyric-inner').children, // 歌词列表p元素集合
            playMode: con.querySelector('.mode'), //播放模式
            playButton: con.querySelector('.play-pause'), //播放按钮
            playPrev: con.querySelector('.prev'), //上一首
            playNext: con.querySelector(".next"), //下一首
            playProgress: {//播放进度条
                progress: con.querySelector(".progress"),
                cur: con.querySelector(".progress-curr"),
                bar: con.querySelector(".progress-slider"),
                load: con.querySelector(".progress-load")
            },
            volProgress: {//音量条
                progress: con.querySelector(".cp-vol-inner"),
                cur: con.querySelector(".cp-volume"),
                bar: con.querySelector(".cp-volume-slider")
            },
            volumeIcon: con.querySelector(".cp-volume-icon"), //音量Icon图标
            currentTime: con.querySelector(".current-time").children,
        }

        this.private = {
            UpdateProId: 0,
            lyricIsMouseOver: false,
            innerfHeight: this.dom.lyricInnerf.getBoundingClientRect().height / 2,
            innerHeight: 0,
            isProgressEnterMove: false,
            isEnterMouseScroll: false,
        }

        this._initAudio();
        this._bindEvents();
    }

    _initAudio() {
        let audio = document.createElement("audio");
        // audio.setAttribute("autoplay", "autoplay");
        audio.volume = this.defaultVolume;
        if (this.playMusicUrl[0]) {
            audio.src = this.playMusicUrl[0].url;
        }
        this.audio = audio;

        // 默认
        this.drawMode();
        this.drawPlayButtonClick();
    }

    _bindEvents() {
        utils.addEvent(this.dom.lyricContainer, "mouseenter", this.OnlyricMouseOver.bind(this));// 歌词列表的鼠标进入事件
        utils.addEvent(this.dom.lyricContainer, "mousewheel", this.OnlyricScroll.bind(this)); // 歌词列表的鼠标滚动事件
        utils.addEvent(this.dom.playMode, "click", this.OnModeClick.bind(this)); // 播放模式切换点击事件
        utils.addEvent(this.dom.playButton, "click", this.OnPauseClick.bind(this)); // 播放开始/暂停切换点击事件
        utils.addEvent(this.dom.playPrev, "click", this.OnPrevClick.bind(this)); // 上一首点击事件
        utils.addEvent(this.dom.playNext, "click", this.OnNextClick.bind(this)); // 下一首点击事件
        this.ProgressEvent(this.dom.volProgress, "vol"); //音量进度条事件
        this.ProgressEvent(this.dom.playProgress, "progress") //播放进度条事件
        utils.addEvent(this.audio, "canplay", this.OnCanplay.bind(this)); // 播放监听开始
        utils.addEvent(this.audio, "timeupdate", this.OnTimeupdate.bind(this)); // 播放监听中途
        utils.addEvent(this.audio, "ended", this.OnEnded.bind(this)); // 播放监听结束
    }
    OnEnded() { //播放结束
        // console.log("播放结束");
        if (this.playMode === 1) {
            this.audio.play();
            this.dom.lyricInner.style.transform = "translateY(273pxpx)";
        } else {
            this.OnMusicPlay();
        }
    }
    OnCanplay() { // 可以播放
        // console.log("可以播放");
    }
    // 进度条绘制
    OnTimeupdate(e) {
        let value = (this.getPercent() * 100).toFixed(2);
        if (!this.private.isProgressEnterMove) { //如果不是鼠标拖动
            this.drawProgress(value, this.dom.playProgress);
            this.Trephrase();
        }
        this.drawLoadBufferedTime();
        this.setTime(this.getCurrentTime(), this.dom.currentTime[0]);
        this.setTime(this.getDuration(), this.dom.currentTime[1]);
    }

    drawLoadBufferedTime() { // 绘制缓存进度条
        // 更新时间和进度条 (默认一秒会执行多次 需要处理一秒只执行一次更新)
        let time = 0
        if (parseInt(this.audio.currentTime) !== Number(time)) {
            time = parseInt(this.audio.currentTime)
            const timeRanges = this.audio.buffered;
            // 获取已缓存的时间  timeRanges.end(timeRanges.length - 1)
            // 计算百分比 展示进度
            let val = parseInt(timeRanges.end(timeRanges.length - 1) * 100 / this.audio.duration * 100) / 100;
            this.dom.playProgress.load.style.width = val + "%";
        }
    }
    // 进度条监控
    Trephrase() {
        // 当前播放时间
        var aT = this.getCurrentTime();
        this.lyric.map((item, i) => {
            if (this.lyric[0].time > aT) {
                // utils.debounce(() => {
                //     console.log("起始位置");
                //     console.log(this.lyric[0].time, aT);
                // })
            }
            else if (item.str &&
                ((this.lyric[i + 1] && this.lyric[i + 1].time > aT) || (aT - item.time) <= 1) &&
                aT >= item.time) {
                /**
                 * 判断文本内容不为空、 锁定播放时间为  播放语句开始时间到 播放语句结束时间之间 、 当前播* 放时间大于播放语句开始时间
                 * 初始第一句时间到最后一句时间位置 歌词位置时间 <= 当前播放时间 
                 */
                // 如果当前id与上一次的id不一致就进行 高亮及位置更新
                if (i != this.private.UpdateProId || this.private.UpdateProId === 0) {
                    //高亮
                    // if (this.dom.lyricInner.getElementsByClassName('active')[0]) {
                    //     this.dom.lyricInner.getElementsByClassName('active')[0].className = "";
                    // };
                    this.dom.lyricP[this.private.UpdateProId].className = "";
                    this.drawLyricPst(this.dom.lyricP[i]);
                    this.private.UpdateProId = i;
                }
            } else if (this.lyric[this.lyric.length - 1].time < aT) {
                // 最后一句时间结束后的位置
                if (this.lyric.length - 1 != this.private.UpdateProId || this.private.UpdateProId === 0) {
                    this.dom.lyricP[this.private.UpdateProId].className = "";
                    this.drawLyricPst(this.dom.lyricP[this.lyric.length - 1]);
                    this.private.UpdateProId = this.lyric.length - 1;
                }

            }
        });
    }
    // 设置播放内容
    setMusicUrl(arr) {
        if (arr) {
            this.playMusicUrl = arr;
            this.playCurIdx = 0;
            this.ReplaceSong(this.playMusicUrl[this.playCurIdx].url);
        }
    }
    /** 歌词p元素绘制
     * @param {elem} p 
     */
    drawLyricPst(p) { //歌词p元素绘制
        if (this.private.isEnterMouseScroll === false) {
            let scrollTransformY = this.private.innerfHeight - p.offsetTop;
            this.dom.lyricInner.style.transform = "translateY(" + scrollTransformY + "px)";
        }
        p.className = "active";
    }
    /**设置音量
     * @num (0-100)
     */
    setMusicVolume(num) {// 设置音量
        this.defaultVolume = num / 100;
        this.audio.volume = num / 100;
    }
    /**设置当前播放ID
     * @param {*number} idx 
     */
    setCurrentIdx(idx) {
        if (idx < this.playMusicUrl.length) {
            if (idx !== this.playCurIdx) {
                this.playCurIdx = idx;
                this.ReplaceSong(this.playMusicUrl[this.playCurIdx].url);
            } else {
                if (this.audio.paused) {
                    this.audio.play();
                    this.drawPlayButtonClick();
                }
            }
        }
    }
    OnMusicPlay() { // 音乐播放
        // 0:循环、1:单曲循环、2:随机循环
        switch (this.playMode) {
            case 0: //0:循环
                this.playCurIdx >= this.playMusicUrl.length - 1 ? this.playCurIdx = 0 : this.playCurIdx++;
                this.ReplaceSong(this.playMusicUrl[this.playCurIdx].url);
                break;
            case 1: //1:单曲循环
                this.ReplaceSong(this.playMusicUrl[this.playCurIdx].url);
                break;
            case 2: //2:随机循环
                this.playCurIdx = parseInt(Math.random() * ((this.playMusicUrl.length - 1) - 0 + 1) + 0, 10);
                this.ReplaceSong(this.playMusicUrl[this.playCurIdx].url);
                break;
        }
    }
    /** 设置歌曲正在播放的时间
     * @param time {number} 时间，单位秒
     */
    setCurrentTime(time) {
        if (time !== 0) {
            time = Math.min(time, this.getDuration());
            time = Math.max(0, time);
            var buffered = this.audio.buffered;
            var start = buffered.start(0);
            var end = buffered.end(0);
            time = Math.max(start, Math.min(end, time));
        }
        this.audio.currentTime = time;
    }
    /** 设置时间
    * @param time {number} 时间，单位秒
    * @param ele {jQuery} 元素
    */
    setTime(time, ele) {
        var minute = MusicUtils.fillByZero(Math.floor(time / 60), 2);
        var second = MusicUtils.fillByZero(Math.floor(time % 60), 2);
        ele.innerHTML = minute + ':' + second;
    }
    /** 获取当前歌曲已播放的百分比
     * @returns {number}
     */
    getPercent() {
        return this.getCurrentTime() / this.getDuration();
    }
    /** 获取正在播放歌曲的当前时间
     * @returns {number} 
     */
    getCurrentTime() {
        return this.audio.currentTime;
    }
    /** 获取当前歌曲的总时长
    * @returns {number}   
    */
    getDuration() {
        return this.audio.duration;
    }
    /** 更换播放信息
    * @src 播放url {String}
    */
    ReplaceSong(src) {
        this.audio.src = src;
        this.setCurrentTime(0);
        this.drawProgress(0, this.dom.playProgress);
        this.audio.play();
        this.drawPlayButtonClick();
    }
    ProgressEvent(opt, pro) { //进度条事件
        let progressWidth, // 进度条的整个宽度
            scrollValuePx; // 实际要滚动的距离 (px,单击事件的距离) 用于接收最终值
        let BarScrollValPx, // 实际滚动的距离 (px,拖拽滚动的距离) 用于接收滚动距离
            BarOffset, // 进度条的button的点击位置距离左边的距离
            clientleftVal; // 进度条距离浏览器左边的距离
        // isEnterMove = false; // 判断是否进入拖动事件
        let $this = this;
        utils.addEvent(opt.progress, "click", PlayprogressClick.bind(this)); //进度条点击事件
        utils.addEvent(opt.bar, "mousedown", function (e) {
            let event = e || window.event;
            BarScrollValPx = 0;
            BarOffset = e.offsetX;
            clientleftVal = event.clientX - this.offsetLeft;
            progressWidth = opt.progress.getBoundingClientRect().width;
            utils.addEvent(document, "mousemove", mouseMove);
            utils.addEvent(document, "mouseup", mouseUp);
            utils.cancelBubble(e);
        });

        function mouseMove(e) {
            $this.private.isProgressEnterMove = true;
            // isEnterMove = true; //是否拖动
            let event = e || window.event;
            BarScrollValPx = event.clientX - clientleftVal + BarOffset;
            if (BarScrollValPx < 0)
                BarScrollValPx = 0;
            else if (BarScrollValPx >= progressWidth)
                BarScrollValPx = progressWidth;
            else if (BarScrollValPx > scroll.offsetWidth - opt.bar.offsetWidth)
                BarScrollValPx = scroll.offsetWidth - opt.bar.offsetWidth;
            opt.cur.style.width = BarScrollValPx + "px";
            opt.bar.style.left = BarScrollValPx + "px";
            //防止选择内容--当拖动鼠标过快时候，弹起鼠标，bar也会移动，修复bug
            window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
        }

        function mouseUp(e) {
            if ($this.private.isProgressEnterMove) { //是否拖动
                scrollValuePx = BarScrollValPx;
                $this.private.isProgressEnterMove = false;
            }
            utils.removeEvent(document, "mousemove", mouseMove)
            utils.removeEvent(document, "mouseup", mouseUp)
        }

        function PlayprogressClick(e) {// 进度条单击事件
            progressWidth = opt.progress.getBoundingClientRect().width;
            if (e.target === opt.progress || e.target === opt.cur || e.target === opt.load) {
                scrollValuePx = e.offsetX;
                this.drawProgress(((scrollValuePx / progressWidth * 100).toFixed(2)), {
                    cur: opt.cur,
                    bar: opt.bar
                });
            } else if (e.target === opt.bar) {
                scrollValuePx = scrollValuePx + (e.offsetX - opt.bar.offsetWidth / 2);
                this.drawProgress(((scrollValuePx / progressWidth * 100).toFixed(2)), {
                    cur: opt.cur,
                    bar: opt.bar
                });
            }
            let vpx = (scrollValuePx / progressWidth * 100).toFixed(2);
            if (pro === 'vol') {
                this.setMusicVolume(vpx);
            } else if (pro === "progress") {
                this.setCurrentTime(vpx / 100 * this.getDuration());
                if (this.audio.paused) {
                    this.audio.play();
                    this.drawPlayButtonClick();
                }
            }
        }
    }
    drawProgress(value, opt) {// 绘制进度条
        opt.cur.style.width = value + "%";
        opt.bar.style.left = value + "%";
    }
    OnPrevClick(e) {// 上一首点击事件
        this.playCurIdx <= 0 ? this.playCurIdx = this.playMusicUrl.length - 1 : this.playCurIdx--;
        this.OnMusicPlay();
    }
    OnNextClick(e) {// 下一首点击事件
        this.playCurIdx >= this.playMusicUrl.length - 1 ? this.playCurIdx = 0 : this.playCurIdx++;
        this.OnMusicPlay();
    }
    OnModeClick(e) {// 播放模式切换点击事件
        this.playMode >= this.modeArr.length - 1 ? this.playMode = 0 : this.playMode++;
        this.drawMode();
    }
    drawMode() {// 播放模式切换
        MusicUtils.modeSwitch(this.dom.playMode, this.modeArr, this.playMode);
    }
    OnPauseClick() { // 播放开始/暂停切换点击事件
        if (this.audio.paused) {
            // 暂停中
            if (this.audio.src) {
                this.audio.play();
            }
        } else {
            // 播放中
            this.audio.pause();
        }
        this.drawPlayButtonClick();
    }
    drawPlayButtonClick() { // 播放开始/暂停切换
        if (this.audio.paused) {
            // 暂停中
            MusicUtils.modeSwitch(this.dom.playButton, this.playButtonArr, 1);
        } else {
            // 播放中
            MusicUtils.modeSwitch(this.dom.playButton, this.playButtonArr, 0);
        }
    }
    OnlyricMouseOver(e) {// 歌词列表的鼠标进入事件
        if (this.private.lyricIsMouseOver === false) { //鼠标进入后 切换鼠标进入状态、获取歌词列表总高度
            this.private.innerHeight = this.dom.lyricInner.getBoundingClientRect().height;
            this.private.lyricIsMouseOver = true;
        }
        utils.addEvent(this.dom.lyricContainer, "mouseleave", onlyricMouseOut.bind(this));// 歌词列表的鼠标离开事件
        function onlyricMouseOut(e) { // 歌词列表的离开事件
            this.private.lyricIsMouseOver = false;
            utils.removeEvent(this.dom.lyricContainer, "mouseleave", onlyricMouseOut);
        }
    }
    OnlyricScroll(e) {// 歌词列表的鼠标滚动事件
        utils.preventDefaultEvent(e); //阻止默认行为
        utils.cancelBubble(e); //取消冒泡

        if (this.private.isEnterMouseScroll === false) {
            this.private.isEnterMouseScroll = true;
            let timer = setTimeout(() => {
                this.private.isEnterMouseScroll = false;
                clearTimeout(timer);
            }, 1000);
        }

        let scrollTransformY = parseInt(this.dom.lyricInner.style.transform.split("(")[1]); // 获取已滚动距离
        if (e.wheelDelta > 0) {
            scrollTransformY += 30;
            if (scrollTransformY > this.private.innerfHeight) { // 父级高度的一半
                scrollTransformY = this.private.innerfHeight;
            }
        } else if (e.wheelDelta < 0) {
            scrollTransformY -= 30;
            if (scrollTransformY < this.private.innerfHeight - this.private.innerHeight) { // 底部距离父级的一半
                scrollTransformY = this.private.innerfHeight - this.private.innerHeight;
            }
        }
        this.dom.lyricInner.style.transform = "translateY(" + scrollTransformY + "px)"
    }
}


export default Music;